﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SceneEngine;

namespace SceneEditor
{
    public partial class Editor
    {
        private void propertyGrid_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
        {
            if (e.NewSelection.PropertyDescriptor == null
                || e.OldSelection == null
                || e.OldSelection.PropertyDescriptor == null
                || e.NewSelection.PropertyDescriptor.Name != e.OldSelection.PropertyDescriptor.Name)
            {
                SetOldValues();
            }
        }
        private void propertyGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            GridItem changedItem = e.ChangedItem;

            GridItem gridItem = GetRootGridItem(e.ChangedItem);
            string propertyName = gridItem.PropertyDescriptor.Name;

            gizmo.Transforms.UpdateBounds();
            editor.Viewport.Focus();

            undoActions.Push(new EditPropertyAction(gizmo.Transforms.Objects.ToArray(),
                oldValues, propertyName), true);
        }

        private void undoActions_Changed(object sender, ChangedEventArgs e)
        {
            editor.btnUndo.Enabled = undoActions.Count > 0;
            changesMade = true;

            if (!editor.Text.Contains("*"))
                editor.Text += " * ";

            if (e.ClearList)
                redoActions.Clear();
        }
        private void redoActions_Changed(object sender, ChangedEventArgs e)
        {
            editor.btnRedo.Enabled = redoActions.Count > 0;
            changesMade = true;

            if (!editor.Text.Contains("*"))
                editor.Text += " * ";
        }

        private void btnRedo_Click(object sender, EventArgs e)
        {
            if (editor.btnRedo.Enabled == false)
                return;

            EditAction action = redoActions.Pop();

            if (action != null)
            {
                action.Redo();
                editor.propertyGrid.Refresh();

                if (action is MoveAction || action is RotateAction)
                {
                    gizmo.Transforms.UpdateBounds();
                }
                else if (action is RemoveObjectAction)
                {
                    RemoveObjectAction removeAction = (RemoveObjectAction)action;

                    editor.tvObjects.BeginUpdate();

                    if (string.IsNullOrEmpty(removeAction.RootNodeToDelete) == false)
                    {
                        TreeNode nodeToRemove = editor.tvObjects.GetNodeFromGroupPath(removeAction.RootNodeToDelete);
                        nodeToRemove.Remove();
                    }

                    foreach (BaseObject baseObject in removeAction.Targets)
                    {
                        if (gizmo.Transforms.Objects.Contains(baseObject.Name))
                        {
                            gizmo.Transforms.Remove(baseObject.Name);
                        }

                        if (string.IsNullOrEmpty(removeAction.RootNodeToDelete))
                        {
                            RemoveObjectFromTree(baseObject);
                        }
                    }

                    editor.tvObjects.EndUpdate();
                }
                else if (action is AddObjectAction)
                {
                    AddObjectAction addAction = (AddObjectAction)action;

                    editor.tvObjects.BeginUpdate();

                    foreach (BaseObject entity in addAction.Targets)
                    {
                        AddObjectToTree(entity);
                    }

                    editor.tvObjects.EndUpdate();
                }

                undoActions.Push(action, false);
            }

            editor.btnRedo.Enabled = redoActions.Count != 0;
        }
        private void btnUndo_Click(object sender, EventArgs e)
        {
            if (editor.btnUndo.Enabled == false)
                return;

            EditAction action = undoActions.Pop();

            if (action != null)
            {
                action.Undo();
                editor.propertyGrid.Refresh();

                if (action is MoveAction || action is RotateAction)
                {
                    gizmo.Transforms.UpdateBounds();
                }
                else if (action is AddObjectAction)
                {
                    AddObjectAction addAction = (AddObjectAction)action;

                    foreach (BaseObject baseObject in addAction.Targets)
                    {
                        if (gizmo.Transforms.Objects.Contains(baseObject.Name))
                        {
                            gizmo.Transforms.Remove(baseObject.Name);
                        }

                        RemoveObjectFromTree(baseObject);
                    }
                }
                else if (action is RemoveObjectAction)
                {
                    RemoveObjectAction removeAction = (RemoveObjectAction)action;

                    editor.tvObjects.BeginUpdate();

                    foreach (BaseObject entity in removeAction.Targets)
                    {
                        AddObjectToTree(entity);
                    }

                    editor.tvObjects.EndUpdate();
                }
                redoActions.Push(action, false);
            }

            editor.btnUndo.Enabled = undoActions.Count != 0;
        }

        private void tsPreferences_Click(object sender, EventArgs e)
        {
            ViewSettingsForm viewSettings = new ViewSettingsForm();

            //viewSettings.tbVisDist.Value = (decimal)environment.VisibleDistance;

            //viewSettings.cbFogEnabled.Checked = environment.FogEnabled;
            //viewSettings.tbFogStart.Value = (decimal)environment.FogStartDistance;
            //viewSettings.tbFogEnd.Value = (decimal)environment.FogEndDistance;

            //System.Drawing.Color colour = System.Drawing.Color.FromArgb((int)(environment.FogColor.X * 255),
            //    (int)(environment.FogColor.Y * 255), (int)(environment.FogColor.Z * 255));

            //viewSettings.btnFogColour.SelectedColor = colour;

            //viewSettings.tbFadeStart.Value = (decimal)environment.ShadowFadeStartDistance;
            //viewSettings.tbFadeEnd.Value = (decimal)environment.ShadowFadeEndDistance;
            //viewSettings.tbCastDist.Value = (decimal)environment.ShadowCasterDistance;

            //if (viewSettings.ShowDialog() == DialogResult.OK)
            //{
            //    environment.VisibleDistance = (float)viewSettings.tbVisDist.Value;

            //    environment.FogEnabled = viewSettings.cbFogEnabled.Checked;
            //    environment.FogStartDistance = (float)viewSettings.tbFogStart.Value;
            //    environment.FogEndDistance = (float)viewSettings.tbFogEnd.Value;

            //    environment.FogColor = new Color(viewSettings.btnFogColour.SelectedColor.R, viewSettings.btnFogColour.SelectedColor.G,
            //        viewSettings.btnFogColour.SelectedColor.B, viewSettings.btnFogColour.SelectedColor.A).ToVector3();

            //    environment.ShadowFadeStartDistance = (float)viewSettings.tbFadeStart.Value;
            //    environment.ShadowFadeEndDistance = (float)viewSettings.tbFadeEnd.Value;
            //    environment.ShadowCasterDistance = (float)viewSettings.tbCastDist.Value;
            //}
        }

        private void HandleDestroyed(object sender, EventArgs e)
        {
            Game.Exit();
        }
        private void Viewport_SizeChanged(object sender, EventArgs e)
        {
            PresentationParameters parameters = GraphicsDevice.PresentationParameters;

            parameters.BackBufferWidth = editor.Viewport.Width;
            parameters.BackBufferHeight = editor.Viewport.Height;

            GraphicsDevice.Reset(parameters);

            if (camera != null)
            {
                camera.UpdateProjection();
            }
        }

        private void editor_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (changesMade == false && terrainChangesMade == false && colorMapChangesMade == false)
            {
                return;
            }

            e.Cancel = PromptSaveChanges();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox box = new AboutBox();
            box.Show();
        }

        private void tsSolid_Click(object sender, EventArgs e)
        {
            if (editor.tsSolid.Checked)
                return;

            editor.tsSolid.Checked = true;
            editor.tsWire.Checked = false;
        }
        private void tsWire_Click(object sender, EventArgs e)
        {
            if (editor.tsWire.Checked)
                return;

            editor.tsWire.Checked = true;
            editor.tsSolid.Checked = false;
        }

        private void toolControl_MouseClick(object sender, MouseEventArgs e)
        {
            for (int i = 0; i < editor.toolControl.TabCount; i++)
            {
                if (editor.toolControl.GetTabRect(i).Contains(e.X, e.Y))
                {
                    if (editor.toolControl.Width == 30)
                    {
                        editor.toolControl.Width = 292;
                        editor.toolControl.TabPages[i].Show();

                        return;
                    }
                }
            }
        }

        private void btnHideProperties_Click(object sender, EventArgs e)
        {
            editor.toolControl.TabPages[2].Hide();
            editor.toolControl.Width = 30;
        }
        private void btnHideModels_Click(object sender, EventArgs e)
        {
            editor.toolControl.TabPages[1].Hide();
            editor.toolControl.Width = 30;
        }
        private void btnHideScene_Click(object sender, EventArgs e)
        {
            editor.toolControl.TabPages[0].Hide();
            editor.toolControl.Width = 30;
        }

        private void Default_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "MouseControls")
            {
                Vector3 oldDirection = camera.Forward;

                if (Preferences.Default.MouseControls && camera is MayaStyleCamera == false)
                    camera = new MayaStyleCamera(camera.Position, camera.Speed);
                else if (!Preferences.Default.MouseControls && camera is Camera == false)
                    camera = new Camera(camera.Position, camera.Speed);

                EngineGlobals.Camera = camera;
            }
        }

        private void tsOptions_Click(object sender, EventArgs e)
        {
            if (preferences == null)
                preferences = new PreferencesForm();

            preferences.tbLineCount.Value = Preferences.Default.GridLineCount;
            preferences.tbSpacing.Value = Preferences.Default.GridSpacing;

            preferences.cbShowGrid.Checked = Preferences.Default.GridVisible;

            byte red = Preferences.Default.GridColor.R;
            byte green = Preferences.Default.GridColor.G;
            byte blue = Preferences.Default.GridColor.B;

            preferences.btnColor.SelectedColor = System.Drawing.Color.FromArgb(255, red, green, blue);

            preferences.tbSpeed.Value = (decimal)camera.Speed;

            if (preferences.ShowDialog() == DialogResult.OK)
            {
                gridLines = (int)preferences.tbLineCount.Value;
                gridSpacing = (int)preferences.tbSpacing.Value;

                gizmo.GridSpacing = gridSpacing;

                byte r = preferences.btnColor.SelectedColor.R;
                byte g = preferences.btnColor.SelectedColor.G;
                byte b = preferences.btnColor.SelectedColor.B;

                Color color = new Color(r, g, b);

                InitializeGrid(gridSpacing, gridLines, color);

                camera.Speed = (float)preferences.tbSpeed.Value;

                Preferences.Default.GridLineCount = gridLines;
                Preferences.Default.GridSpacing = (int)gridSpacing;
                Preferences.Default.GridColor = color;
                Preferences.Default.GridVisible = preferences.cbShowGrid.Checked;

                Preferences.Default.CameraSpeed = camera.Speed;
                Preferences.Default.Save();
            }
        }
    }
}
